package com.legendshop.code;

import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


import com.legendshop.dao.Utils;
import com.legendshop.dao.persistence.Column;
import com.legendshop.dao.persistence.Id;
import com.legendshop.dao.persistence.Table;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import com.legendshop.code.config.Config;
import com.legendshop.code.db.DbType;
import com.legendshop.code.freemarker.AbstractBulidTemplet;
import com.legendshop.code.freemarker.BulidTemplet;
import com.legendshop.code.sequence.Sequence;


public class SequenceGen {
	private final static Logger logger = LoggerFactory.getLogger(AbstractBulidTemplet.class);
	private static final String ABS_PATH = "C:/Java/Projects/LegendShop20140517/legendshop_model/src/java/";
	private static final String BUILDER_PATH = "C:/Java/Projects/LegendShop20140517/legendshop_model/src/java/com/legendshop/model/entity/";

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		List<Info> infoList = new ArrayList<Info>();
		List<Class<?>> list = new ArrayList<Class<?>>();
		JdbcTemplate jdbcTemplate =  new JdbcTemplate(DbType.getDataSource());
		try {
			list = SequenceGen.getTempletClass(list, BUILDER_PATH);
			for (Class clazz : list) {
				System.out.println(clazz.getSimpleName());
				Info info = new Info();
				info.setTable(getTableName(clazz));
				parssClassInfo(clazz,info);
				if(info.getSequenceName() != null){
					infoList.add(info);
				}
			}
			for (Info info : infoList) {
				System.out.println("info = " + info);
				parseSequence(jdbcTemplate, info);
			}
			
		} catch (Exception e) {
			logger.error("SourceGen error:", e);
		}
	}
	
	private static void parseSequence(JdbcTemplate jdbcTemplate, Info info){
		String sql = "select sequence_name, next_val from ls_sequence where sequence_name = ?";
		List<Sequence> sequenceList = jdbcTemplate.query(sql, new Object[] { info.getSequenceName()},  new RowMapper<Sequence>() {
			@Override
			public Sequence mapRow(ResultSet rs, int i) throws SQLException {
				Sequence seq = new Sequence();
				seq.setSequenceName(rs.getString("sequence_name"));
				seq.setNextVal(rs.getLong("next_val"));
				return seq;
			}
		});
		sql = "select max(" + info.getId() + ") from " + info.getTable();
		Integer maxValue = jdbcTemplate.queryForObject(sql, Integer.class) + 1;
		if(sequenceList != null && sequenceList.size() > 0){
			sql = "insert into ls_sequence(sequence_name, next_val) values (?,?);";
			jdbcTemplate.update(sql, new Object[]{info.getSequenceName(),maxValue});
		}else{
			Sequence seq = sequenceList.get(0);
			sql = "update ls_sequence set next_val = ? where sequence_name = ?";
			jdbcTemplate.update(sql, new Object[]{maxValue, seq.getSequenceName()});
		}
		
		
	}

	private static void parssClassInfo(Class<?> clazz,Info info) {
		Map<String, Method> getters = Utils.findPublicGetters(clazz);
		try {
			for (String property : getters.keySet()) {
				Method getter = getters.get(property);
				Id id = getter.getAnnotation(Id.class);
				if (id != null) {
					Column column = getter.getAnnotation(Column.class);
					if(column != null){
						info.setId(column.name());
					}else{
						info.setId(property);
					}
					
					com.legendshop.dao.persistence.TableGenerator tableGenerator = getter.getAnnotation(com.legendshop.dao.persistence.TableGenerator.class);
					if(tableGenerator != null){
						info.setSequenceName(tableGenerator.pkColumnValue());
					}
				}
			}
		} catch (Exception e) {
			throw new RuntimeException("clazz " + clazz, e);
		}

	}


	/**
	 * 遍历生成相关的模板文件
	 * 
	 * @param list
	 * @throws Exception
	 */
	protected static void exec(List<Class<?>> list) {
		String[] tables = Config.getInstance().getTableList();
		for (String table : tables) {
			for (Class<?> clazz : list) {
				BulidTemplet bulidTemplet = null;
				try {
					bulidTemplet = (BulidTemplet) clazz.newInstance();
				} catch (InstantiationException e) {
					logger.error("InstantiationException :", e);
					return;
				} catch (IllegalAccessException e) {
					logger.error("IllegalAccessException :", e);
					return;
				}
				bulidTemplet.buildSourceFile(table);
			}
		}
	}

	/**
	 * 找到BulidTemplet接口的所有非抽象实现类
	 * 
	 * @param list
	 * @param path
	 * @return
	 * @throws Exception
	 */
	protected static List<Class<?>> getTempletClass(List<Class<?>> list, String path) throws Exception {
		if (path.contains(".svn")) {
			return list;
		}
		File[] files = new File(path).listFiles();

		if (files != null) {
			for (File file : files) {
				if (file.isDirectory()) {
					getTempletClass(list, path + file.getName() + "/");
				} else {
					String className = path.replace(ABS_PATH, "").replace("/", ".") + file.getName();
					className = className.substring(0, className.length() - 5);
					// Class<?> clazz =
					// Thread.currentThread().getContextClassLoader().loadClass(className);
					Class<?> clazz = Class.forName(className);
					if (!Modifier.isAbstract(clazz.getModifiers()) && Modifier.isPublic(clazz.getModifiers())) {
						if (clazz.getAnnotation(Table.class) != null) {
							list.add(clazz);
						}
					}
				}
			}
		}
		return list;
	}
	
	/**
	 * Gets the table name.
	 * 
	 * @param entityClass
	 *            the entity class
	 * @return the table name
	 */
	private static String getTableName(Class<?> entityClass) {
		String name = entityClass.getSimpleName();
		Table table = entityClass.getAnnotation(Table.class);
		if (table != null && !"".equals(table.name()))
			name = table.name();
		return name;
	}

}

